/* eslint-disable @typescript-eslint/no-unused-vars */
/* @author: seagull  @change:有限状态机基类
 * @date: 2025/04/24 22:44 */

/**
* @example 用法：
*  1. 定义状态枚举 enum State {}
*  2. 创建状态机实例 const fsm = new StateMachine<State, Event>();
*  3. 添加状态 fsm.addState(State.IDLE, { onEnter: () => { } });
*  4. 添加状态转换规则 fsm.addTransition(State.IDLE, State.RUN, Event.RUN);
*  5. 初始化状态 fsm.setState(State.IDLE);
*/

/**
 * 有限状态机基础类
 * @template T 状态类型（建议使用枚举或字符串字面量）
 * @template K 事件类型（触发状态转换的条件类型）
 */
export class StateMachine<T, K = void> {
    private _currentState: T | null = null;
    private states: Map<T, StateConfig<T, K>> = new Map();
    private transitions: Transition<T, K>[] = [];

    /** 获取当前状态 */
    public get currentState(): T | null {
        return this._currentState;
    }

    /**
     * 添加状态
     * @param state 状态标识
     * @param config 状态配置
     */
    addState(state: T, config: Partial<StateConfig<T, K>> = {}): this {
        this.states.set(state, {
            onEnter: config.onEnter || (() => { }),
            onExit: config.onExit || (() => { }),
            onUpdate: config.onUpdate || (() => { })
        });
        return this;
    }

    /**
     * 添加状态转换规则
     * @param from 源状态
     * @param to 目标状态
     * @param condition 转换条件（触发事件或判断函数）
     */
    addTransition(from: T | T[], to: T, condition: ConditionFn<K> | K): this {
        const conditionFn = typeof condition === 'function'
            ? condition : (event: K) => event === condition;

        const sources = Array.isArray(from) ? from : [from];
        sources.forEach(source => {
            this.transitions.push({
                from: source,
                to,
                condition: conditionFn as ConditionFn<K>
            });
        });
        return this;
    }

    /** 更新状态机 */
    update(dt: number): void {
        if (!this._currentState) return;
        const stateConfig = this.states.get(this._currentState);
        stateConfig?.onUpdate?.(dt);
    }

    /**
     * 触发状态转换检查
     * @param event 触发事件（可选）
     */
    trigger(event?: K): boolean {
        if (!this._currentState) return false;

        const validTransitions = this.transitions.filter(
            t => t.from === this._currentState && t.condition(event)
        );

        if (validTransitions.length > 0) {
            this.setState(validTransitions[0].to);
            return true;
        }
        return false;
    }

    /** 强制设置状态（建议仅在初始化时使用） */
    setState(newState: T): void {
        if (!this.states.has(newState)) {
            throw new Error(`State ${newState} not registered`);
        }

        if (this._currentState === newState) return;

        // 执行旧状态退出逻辑
        const oldStateConfig = this.states.get(this._currentState!);
        oldStateConfig?.onExit?.();

        // 更新当前状态
        this._currentState = newState;

        // 执行新状态进入逻辑
        const newStateConfig = this.states.get(newState)!;
        newStateConfig.onEnter?.();
    }
}

/** 状态配置接口 */
interface StateConfig<T, K> {
    onEnter?: () => void;
    onExit?: () => void;
    onUpdate?: (dt: number) => void;
}

/** 状态转换规则接口 */
interface Transition<T, K> {
    from: T;
    to: T;
    condition: ConditionFn<K>;
}

/** 条件判断函数类型 */
type ConditionFn<K> = (event?: K) => boolean;
